package org.shopen.puremvc.model
{
	import flash.text.StyleSheet;
	import flash.utils.Dictionary;
	
	import mx.collections.ArrayCollection;
	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;
	
	import org.puremvc.as3.patterns.proxy.Proxy;
	import org.shopen.puremvc.ApplicationParameters;
	import org.shopen.puremvc.model.domain.theory.Stage;
	import org.shopen.puremvc.model.domain.theory.Theory;
	import org.shopen.puremvc.model.domain.theory.TheoryMeta;
	import org.shopen.puremvc.model.utils.TextLoader;

	public class TheoryProxy extends Proxy
	{
		public static const NAME : String = "TheoryProxy";
		
		public static const THEORY_PAGE_LOADED : String = NAME + "." + "THEORY_PAGE_LOADED";
		public static const THEORY_PAGE_LOAD_FAILED : String = NAME + "." + "THEORY_PAGE_LOAD_FAILED";
		public static const THEORY_PAGE_STYLE_LOAD_FAILED : String = NAME + "." + "THEORY_PAGE_STYLE_LOAD_FAILED";
		public static const THEORY_META_INITIALIZED : String = NAME + "." + "THEORY_META_INITIALIZED";
		
		//Dictionary with styleUrl - styleSheet entries
		protected var cachedStyles : Dictionary = new Dictionary();
		
		public function get stage() : Stage
		{
			return getData() as Stage;
		}
		
		public function get theorysMeta() : ArrayCollection
		{
			var result : ArrayCollection = new ArrayCollection();
			for each (var theory : Theory in stage.theoryItems)
			{
				result.addItem(theory.meta);
			}
			return result;
		}
		
		protected var currentMeta : TheoryMeta = null;
		
		public function TheoryProxy(data:Object=null)
		{
			super(TheoryProxy.NAME, data);
		}
		
		override public function getProxyName():String
		{
			return TheoryProxy.NAME;
		}
		
		public function initData(data : Stage) : void
		{
			setData(data);
			sendNotification(TheoryProxy.THEORY_META_INITIALIZED, theorysMeta);
		}
		
		protected function getTheory(meta : TheoryMeta) : Theory
		{
			var result : Theory = null;
			for each (var page : Theory in stage.theoryItems)
			{
				if (page.meta.htmlUrl == meta.htmlUrl && page.meta.id == meta.id)
				{
					result = page;
					break;
				}
			}
			return result;
		}
		
		public function loadPage(meta : TheoryMeta, id : String) : void
		{
			loadPageHtml(meta, id);
			
		}
		
		private function loadPageHtml(meta : TheoryMeta, id : String) : void
		{
			var url : String = ApplicationParameters.DATA_FOLDER + ApplicationParameters.OS_DELIMITER + meta.htmlUrl;
			var loader : TextLoader = new TextLoader(id, url, meta);
			loader.addEventListener(ResultEvent.RESULT, loadPageHtmlResultListener);
			loader.addEventListener(FaultEvent.FAULT, loadPageHtmlFaultListener);
			loader.load();
		}
		
		private function loadPageHtmlResultListener(event : ResultEvent) : void
		{
			var loader : TextLoader = event.target as TextLoader;
			var meta : TheoryMeta = loader.vo as TheoryMeta;
			var theory: Theory = getTheory(meta);
			theory.htmlText = loader.result;
			
			// in case style specified 
			if (meta.styleUrl)
			{
				// if style cached - do not load
				if (cachedStyles[meta.styleUrl])
				{
					theory.styleSheet = cachedStyles[meta.styleUrl] as StyleSheet;
					sendNotification(TheoryProxy.THEORY_PAGE_LOADED, theory, loader.id);
				}
				// otherwise load style
				else
				{
					loadPageStyle(meta, loader.id)
				}
			}
			else
			{
				sendNotification(TheoryProxy.THEORY_PAGE_LOADED, theory, loader.id);
			}
		}
		
		private function loadPageHtmlFaultListener(event : FaultEvent) : void
		{
			var loader : TextLoader = event.target as TextLoader;
			sendNotification(TheoryProxy.THEORY_PAGE_LOAD_FAILED, event, loader.id);
		}
		
		private function loadPageStyle(meta : TheoryMeta, id : String) : void
		{
			var url : String = ApplicationParameters.DATA_FOLDER + ApplicationParameters.OS_DELIMITER + meta.styleUrl;
			var loader : TextLoader = new TextLoader(id, url, meta);
			loader.addEventListener(ResultEvent.RESULT, loadPageStyleResultListener);
			loader.addEventListener(FaultEvent.FAULT, loadPageStyleFaultListener);
			loader.load();
		}
		
		private function loadPageStyleResultListener(event : ResultEvent) : void
		{
			var loader : TextLoader = event.target as TextLoader;
			var meta : TheoryMeta = loader.vo as TheoryMeta;
			var theory: Theory = getTheory(meta);
			var styleSheet : StyleSheet = new StyleSheet();
			styleSheet.parseCSS(loader.result);
			cachedStyles[meta.styleUrl] = styleSheet;
			theory.styleSheet = styleSheet;
			
			sendNotification(TheoryProxy.THEORY_PAGE_LOADED, theory, loader.id);
		}
		
		private function loadPageStyleFaultListener(event : FaultEvent) : void
		{
			var loader : TextLoader = event.target as TextLoader;
			var meta : TheoryMeta = loader.vo as TheoryMeta;
			var theory: Theory = getTheory(meta);
			sendNotification(TheoryProxy.THEORY_PAGE_LOADED, theory, loader.id);
			sendNotification(TheoryProxy.THEORY_PAGE_STYLE_LOAD_FAILED, event, loader.id);
		}
	}
}